package tsdb;

import com.alibaba.fastjson.JSON;
import com.aliyun.hitsdb.client.TSDB;
import com.aliyun.hitsdb.client.TSDBClientFactory;
import com.aliyun.hitsdb.client.TSDBConfig;
import com.aliyun.hitsdb.client.value.request.*;
import com.aliyun.hitsdb.client.value.response.MultiFieldQueryLastResult;
import com.aliyun.hitsdb.client.value.response.MultiFieldQueryResult;
import com.aliyun.hitsdb.client.value.type.Aggregator;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author caihe
 * @date 2021/12/28 17:46
 */
public class TsdbDemo {

    //    public static void main(String[] args) {
//        // 1642388063730 1640685096434
//        long now = System.currentTimeMillis();
//        System.out.println(now - 3600 * 1000 * 24 * 30 + " " + now);
//    }
    //jdbc:lindorm:tsdb:url=http://ld-uf65nx39go0j575xu-proxy-tsdb-pub.lindorm.rds.aliyuncs.com:8242
    private static final String HOST = "ld-uf65nx39go0j575xu-proxy-tsdb-pub.lindorm.rds.aliyuncs.com";


    private static final Integer PORT = 8242;

    private static TSDB tsdb = null;
    private static TSDBConfig config = null;

    static {
        // 创建 TSDB 对象
        config = TSDBConfig.address(HOST, PORT).basicAuth("root", "root").config();
        tsdb = TSDBClientFactory.connect(config);
    }

    public static void main(String[] args) throws Exception {
        long now = System.currentTimeMillis();
        System.out.println(now - 3600 * 1000 * 24 * 30 + " " + now);
        write();
        //readV2();
//        write();
//        asdasd();

        Date start = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2019-12-21 00:00:00");
        Date end = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2026-12-21 00:00:00");


        deltaTest("zenith_plate_info_v2", "license", "浙FZ009Q", start, end);
        tsdb.close();
    }

    public static void deltaTest(String table, String tagName, String tagVal, Date start, Date end) {
        long begin = System.currentTimeMillis();
        System.out.println("开始时间------- " + begin);
        MultiFieldSubQueryDetails fieldDetail = MultiFieldSubQueryDetails
                .field("zenith_time")
                .aggregator(Aggregator.NONE)
                .delta(true)
                .dpValue(">=0")
                .build();
        List<MultiFieldSubQueryDetails> multiFieldSubQueryDetails = Arrays.asList(fieldDetail);
        
        MultiFieldSubQuery subQuery = MultiFieldSubQuery.metric(table)
                .tag(tagName, tagVal)
                .tag(tagName, "沪A673R2")
                .fieldsInfo(multiFieldSubQueryDetails)
                .build();
        MultiFieldQuery query = MultiFieldQuery.start(start).end(end).sub(subQuery).build();
        List<MultiFieldQueryResult> multiFieldQueryResults = tsdb.multiFieldQuery(query);
        long over = System.currentTimeMillis();
        System.out.println("结束时间------- " + over);
        System.out.println("耗时：" + (over - begin));
//        multiFieldQueryResults.get(0).getValues().forEach(item -> {
//            String format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss S").format(Long.parseLong(item.get(0).toString()));
//            item.add(format);
//        });
        System.out.println(JSON.toJSONString(multiFieldQueryResults));
    }

    public static void asdasd() {
        MultiFieldSubQueryDetails fieldDetail_1 = MultiFieldSubQueryDetails
                .field("sensor_date_double").aggregator(Aggregator.NONE).delta(true).dpValue(">=1").build();
        List<MultiFieldSubQueryDetails> fieldsDetails = new ArrayList();
        fieldsDetails.add(fieldDetail_1);
        // 创建多值模型子查询
        MultiFieldSubQuery subQuery = MultiFieldSubQuery.metric("sensor1")
                .tag("device_id", "设备编号2")
                .fieldsInfo(fieldsDetails)
                .build();
        // 创建多值模型查询
        MultiFieldQuery query = MultiFieldQuery.start(1627747200000L).end(1641288096330L)
                .sub(subQuery).build();
        List<MultiFieldQueryResult> result = tsdb.multiFieldQuery(query);
        System.out.println(JSON.toJSONString(result));
    }

    public static void write() throws Exception {
        // 该形式会自动创建表  使用sql语句进行删除表会报错
        MultiFieldPoint point = MultiFieldPoint.metric("sensor")
                .tag("device_id", "A000001")
                .tag("region", "east-cn")
                .timestamp(System.currentTimeMillis())
                .field("temperature", 19)
                .field("humidity", 29).build();
        // 同步写入
        tsdb.multiFieldPutSync(point);
    }

    public static void wirte1() {
        /*
         *  通过 multiFieldPutSync() API。
         *  该 API 支持单点和多点(List)写入。
         *
         *  下面是必须写入时必须提供的信息:
         *  Metric: 数据指标的类别。相当于 influxdb 的 Measurement。
         *  Fields: 数据指标的度量信息（相当于指标下的子类别）。即一个 metric 支持多个 fields。如 metric 为 wind，该 metric 可以有多个 fields：direction, speed, direction, description 和 temperature。
         *  Timestamp: 数据点的时间戳
         *  Tags: 时间线额外的信息，如"型号=ABC123"、"出厂编号=1234567890"等。
         */
        MultiFieldPoint multiFieldPoint = MultiFieldPoint.metric("wind")
                .tag("sensor", "95D8-7913")
                .tag("city", "hangzhou")
                .tag("province", "zhejiang")
                .timestamp(System.currentTimeMillis())
                .field("speed", 45.2)
                .field("level", 1.2)
                .field("direction", "S")
                .field("description", "Breeze")
                .build();

        // 同步写入
        tsdb.multiFieldPutSync(multiFieldPoint);
    }


   

    public static void read() throws Exception {
        MultiFieldSubQueryDetails fieldDetail_1 = MultiFieldSubQueryDetails
                .field("speed")
                .aggregator(Aggregator.NONE)
                .dpValue(">=45.2").build();


        List<MultiFieldSubQueryDetails> fieldsDetails = new ArrayList();


        MultiFieldSubQuery subQuery = MultiFieldSubQuery.metric("sensor")
                .tag("device_id", "A000001")
                .fieldsInfo(fieldsDetails)
                .build();
        MultiFieldQuery query = MultiFieldQuery.start(1537170208L).end(1537170209L)
                .sub(subQuery).build();
        List<MultiFieldQueryResult> result = tsdb.multiFieldQuery(query);
        if (result != null) {
            System.out.println("##### Multi-field Query Result : " + JSON.toJSONString(result));
            if (result.size() > 0) {
                System.out.println("##### Multi-field Query Result asMap : " + JSON.toJSONString(result.get(0).asMap()));
            }
        } else {
            System.out.println("##### Empty reply from HiTSDB server. ######");
        }
    }


    /**
     * 获取最新数据
     * <p>
     * multiFieldQueryLast() API。
     * 和单值模型查询方式类似，只是在创建 LastPointSubQuery 时候需要提供 fields 信息。
     * 查询时必须提供的信息:
     * Metric: 代表查询的数据指标，例如"metric":"wind"。
     * Fields: 查询指标下具体的度量（子类比）信息，例如 "speed", "level", "temperature"。
     **/
    public static void readV2() {

        String metric = "sensor";
        // 决定查哪些 field
        List<String> fields = new ArrayList<>();
        fields.add("temperature");
        fields.add("humidity");
        // 根据什么tag进行查询
        Map<String, String> tags = new HashMap<>();
        tags.put("region", "north-cn");
        LastPointQuery lastPointQuery = LastPointQuery.builder()
                .sub(LastPointSubQuery.builder(metric, fields, tags).build()).tupleFormat(true).build();
        List<MultiFieldQueryLastResult> result = tsdb.multiFieldQueryLast(lastPointQuery);
        if (result != null) {
            System.out.println("##### Multi-field Query Last Result : " + JSON.toJSONString(result));
        } else {
            System.out.println("##### Empty reply from HiTSDB server. ######");
        }
    }

}
